﻿//
// (C) Copyright 2009 Irantha Suwandarathna (iranthas@hotmail.com)
// All rights reserved.
//

/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 ********************************************************/


using System;
using System.Data;
using System.Data.Common;
using System.Transactions;

namespace System.Data.EffiProzDB
{
    internal class EffiProzDBEnlistment : IEnlistmentNotification
    {

        internal EffiProzDBTransaction _transaction;
        internal Transaction _scope;
        internal bool _disposeConnection;

        internal EffiProzDBEnlistment(EffiProzDBConnection cnn, Transaction scope)
        {
            lock (this)
            {
                _transaction = cnn.BeginTransaction();
                _scope = scope;

                _scope.EnlistVolatile(this, System.Transactions.EnlistmentOptions.None);
            }
        }

        private void Cleanup(EffiProzDBConnection cnn)
        {
            if (_disposeConnection)
                cnn.Dispose();

            _transaction = null;
            _scope = null;
        }

        #region IEnlistmentNotification Members

        public void Commit(Enlistment enlistment)
        {
            lock (this)
            {
                EffiProzDBConnection cnn = _transaction.Connection;
                cnn._enlistment = null;

                try
                {
                    _transaction.IsValid(true);
                    _transaction.Connection._transactionLevel = 1;
                    _transaction.Commit();

                    enlistment.Done();
                }
                finally
                {
                    Cleanup(cnn);
                }
            }
        }

        public void InDoubt(Enlistment enlistment)
        {
            enlistment.Done();
        }

        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            lock (this)
            {
                if (_transaction.PrepareCommit() == false)
                    preparingEnlistment.ForceRollback();
                else
                    preparingEnlistment.Prepared();
            }
        }

        public void Rollback(Enlistment enlistment)
        {
            lock (this)
            {
                EffiProzDBConnection cnn = _transaction.Connection;
                cnn._enlistment = null;

                try
                {
                    _transaction.Rollback();
                    enlistment.Done();
                }
                finally
                {
                    Cleanup(cnn);
                }
            }
        }

        #endregion
    }
}
